package org.mathcloud.math.core.generic.operator;

import java.util.ArrayList;
import java.util.List;

import org.mathcloud.math.core.common.operator.NaryOperator;
import org.mathcloud.math.core.common.quantity.QuantityObject;
import org.mathcloud.math.core.common.signature.QuantityObjectSignature;
import org.mathcloud.math.core.generic.signature.GenericOperatorObjectSignature;
import org.mathcloud.math.core.generic.signature.GenericQuantityObjectSignature;
import org.webequa.core.generic.operator.GenericOperator;

public abstract class GenericNaryOperator extends GenericOperator implements NaryOperator
{
	public GenericNaryOperator()
	{
		super();
		operands = null;
		res = null;
		signature = new GenericOperatorObjectSignature(0,null,"generic");
	}
	
	@Override
	public void setInputParams(List<QuantityObject> params)
	{
		operands = params;
		((GenericOperatorObjectSignature)signature).setOperandsNumber(params.size());
	}
	public void setInputParams(QuantityObject op1, QuantityObject op2)
	{
		operands = new ArrayList<QuantityObject>();
		operands.add(op1);
		operands.add(op2);
		((GenericOperatorObjectSignature)signature).setOperandsNumber(2);
	}	
	
	@Override
	public void calculate()
	{
		if ((operands!=null)&&(operands.size()>1))
		{
			QuantityObject tmpRes = operands.get(0);
			for (int i=1;i<operands.size();i++)				
			{
				if (getResultSignature(tmpRes, operands.get(i))!=null)
				{
					tmpRes = calculate(tmpRes, operands.get(i));
					if (tmpRes==null) break;
				} else break;
			}
			res = tmpRes;
		}
	}
	@Override
	public QuantityObject getOperand(int n)
	{
		if (operands==null)
			return null;
		else if (n >= operands.size()||n<0)
			return null;
		else return operands.get(n);
	}

	@Override
	public int getOperandOrder()
	{
		return 0;
	}	
	public abstract QuantityObject calculate(QuantityObject op1, QuantityObject op2);
	public QuantityObjectSignature getResultSignature(QuantityObject operand1, QuantityObject operand2)
	{
    if ((operand1!=null)&&(operand2!=null))
    {
      GenericQuantityObjectSignature resSign = (GenericQuantityObjectSignature) 
      	GenericQuantityObjectSignature.getRealNumberSignature();
      if (operand1.getSignature().isComplex()||operand2.getSignature().isComplex())
        resSign.setComplex(true);
      resSign.setDimensionsNumber(Math.max(operand1.getSignature().getDimensionsNumber(),
          operand2.getSignature().getDimensionsNumber()));
      if (resSign.getDimensionsNumber()==operand1.getSignature().getDimensionsNumber())
        resSign.setDimensions(operand1.getSignature().getDimensions());
      else resSign.setDimensions(operand2.getSignature().getDimensions());      
      return resSign;
    } else return null;		
	}
	
	@Override
	public QuantityObjectSignature getResultSignature()
	{
		if (operands!=null)
		{
      GenericQuantityObjectSignature resSign = (GenericQuantityObjectSignature) 
    		GenericQuantityObjectSignature.getRealNumberSignature();
      for (QuantityObject op : operands)
      {
      	QuantityObjectSignature opSign = op.getSignature();
      	if (opSign!=null)
      	{
        	if (opSign.isComplex())
        		resSign.setComplex(true);
        	if (opSign.getDimensionsNumber()>resSign.getDimensionsNumber())
        	{
        		resSign.setDimensionsNumber(opSign.getDimensionsNumber());
        		resSign.setDimensions(opSign.getDimensions());
        	}      		
      	}
      }
			return resSign;
		}

		else return null;
	}
	
	protected List<QuantityObject> operands;
}
